﻿using System.Reflection;
using ThingsEdge.Common.DependencyInjection;
using ThingsEdge.Router;
using Digitalmes.Infrastructure.Common.SerialPorts;
using Digitalmes.Infrastructure.Scada.Handlers;
using Digitalmes.Infrastructure.Services;
using Digitalmes.Infrastructure.Brokers.LedGuide;

namespace Digitalmes.Infrastructure;

public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 配置应用程序应用相关服务。
    /// </summary>
    /// <param name="services"></param>
    public static IServiceCollection AddInfrastructureSteup(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddMemoryCache();
        services.Configure<AppConfig>(configuration.GetSection("App"));

        services.AddSingleton<LedGuideBroker>();

        return services;
    }

    /// <summary>
    /// 注册 HTTP 客户端，使用时带上 <see cref="FromKeyedServicesAttribute"/> 来获取实例。
    /// </summary>
    /// <param name="services"></param>
    /// <param name="key">关键字</param>
    /// <param name="baseUrl">基地址</param>
    /// <returns></returns>
    public static IServiceCollection AddRestClient(this IServiceCollection services, string? key, string baseUrl)
    {
        services.TryAddKeyedTransient<IGalleryClient>(key, (_, _) => new RestGalleryClient(baseUrl));
        return services;
    }

    /// <summary>
    /// 注册串口。
    /// </summary>
    /// <param name="services"></param>
    /// <param name="actionConfig">设置</param>
    /// <returns></returns>
    /// <remarks>
    /// 注册串口后，使用 <see cref="ISerialPortsSwitch"/> 来开启和关闭串口。
    /// 串口成功收到不为空的数据后会发布 <see cref="SerialDataReceivedEvent"/> 事件，若接收出现异常会发布 <see cref="SerialErrorReceivedEvent"/> 事件。
    /// </remarks>
    public static IServiceCollection AddSerialPorts(this IServiceCollection services, Action<SerialPortsConfig>? actionConfig = null)
    {
        SerialPortsConfig config = new();
        actionConfig?.Invoke(config);
        services.ConfigureOptions(config);

        services.AddSingleton<SerialPortsManager>();
        services.AddTransient<ISerialPortsSwitch, SerialPortsSwitch>();

        return services;
    }

    /// <summary>
    /// 注册 Scada 服务。
    /// </summary>
    /// <param name="hostBuilder"></param>
    /// <param name="assemblies">注册 EventBus 的程序集</param>
    public static void AddScada(this IHostBuilder hostBuilder, params Assembly[] assemblies)
    {
        // 注册当前程序集
        List<Assembly> assemblyList =
        [
            typeof(ServiceCollectionExtensions).Assembly,
        ];
        if (assemblies?.Length > 0)
        {
            assemblyList.AddRange(assemblies);
        }

        hostBuilder.AddThingsEdgeRouter()
            .AddDeviceFileProvider()
            .AddDirectMessageRequestHandler<DirectApiHandler>()
            .AddOpsProvider(options =>
            {
                options.HeartbeatShouldAckZero = false;
            })
            .AddEventBus([.. assemblyList]);

        hostBuilder.ConfigureServices((context, services) =>
        {
            services.Configure<ScadaConfig>(context.Configuration.GetSection("Scada"));

            // 注册标记的服务
            services.AddAutoDependencyInjection(typeof(ServiceCollectionExtensions).Assembly);

            // 启动项
            services.AddHostedService<ScadaStartupHostedService>();

            // 注册服务
            services.TryAddKeyedTransient<IReciveMessageHandler, LedGuideRecivedHandler>(nameof(LedGuideRecivedHandler));
        });
    }
}
